package com.macro.cloud.executors;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.concurrent.*;

//打印任务
class PrintTask implements Runnable {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    final int index;

    PrintTask(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        try {
            log.info("打印任务:{} ,开始->当前时间: {} 当前线程id:{}", index, LocalDateTime.now(),
                    Thread.currentThread().getName());
            Thread.sleep(4 * 1000);
            log.info("打印任务:{} ,结束->当前时间: {} 当前线程id:{}", index, LocalDateTime.now(),
                    Thread.currentThread().getName());
            log.info("--------------------------------- ");
        } catch (Exception e) {
            log.error("PrintTask : 异常!!!!! ");
            e.printStackTrace();
        }
    }
}


//打印任务
class PrintDelayTask implements Runnable {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    final int index;

    PrintDelayTask(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        try {
            System.out.println("打印延时任务 :" + index);
            System.out.println("结束->当前时间:  :" + System.currentTimeMillis());
            System.out.println("当前线程id :" + Thread.currentThread().getName());

            log.info("打印延时任务:{} ,结束->当前时间: {} 当前线程id:{}", index, System.currentTimeMillis(),
                    Thread.currentThread().getName());
            log.info("--------------------------------- ");
        } catch (Exception e) {
            log.error("PrintTask : 异常!!!!! ");
            e.printStackTrace();
        }
    }
}


//打印任务
class PrintSingleTask implements Runnable {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    final int index;

    PrintSingleTask(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        try {
            // System.out.println("打印单线程任务 :" + index);
            log.info("打印单线程任务:{} ,结束->  当前线程id:{}", index, Thread.currentThread().getName());
            log.info("--------------------------------- ");
        } catch (Exception e) {
            log.error("PrintSingleTask : 异常!!!!! ");
            e.printStackTrace();
        }
    }
}

/*
*
*
* 、Java 线程池

Java通过Executors提供四种线程池，分别为：
* newCachedThreadPool创建一个可缓存线程池，如果线程池长度超过处理需要，可灵活回收空闲线程，若无可回收，则新建线程。
* newFixedThreadPool 创建一个定长线程池，可控制线程最大并发数，超出的线程会在队列中等待。
* newScheduledThreadPool 创建一个定长线程池，支持定时及周期性任务执行。
* newSingleThreadExecutor 创建一个单线程化的线程池，它只会用唯一的工作线程来执行任务，保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

* */
public class ExecutorsDemo {
    public static final Logger log = LoggerFactory.getLogger(ExecutorsDemo.class);


    /*
    *  1)newCachedThreadPool：
        创建一个可缓存线程池，如果线程池长度超过处理需要，可灵活回收空闲线程，若无可回收，则新建线程。
        * 线程池为无限大，当执行第二个任务时第一个任务已经完成，会复用执行第一个任务的线程，而不用每次新建线程。
    * ：*/

    public void test1() throws InterruptedException {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int index = i;
            PrintTask task = new PrintTask(index);    //构建 index 任务
            Thread.sleep(index * 1000);

            cachedThreadPool.execute(task);    //执行任务
        }
    }


    //---------------------------------------------------------------------------------------------------------------------

    /*
    * (2)newFixedThreadPool：
        创建一个定长线程池，可控制线程最大并发数，超出的线程会在队列中等待。 下面示例中线程池大小为3。
        定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。可参考 PreloadDataCache。
     */

    public void test2() throws InterruptedException {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 10; i++) {
            final int index = i;
            PrintTask task = new PrintTask(index);    //构建 index 任务
            Thread.sleep(2 * 1000);
            fixedThreadPool.execute(task);    //执行任务
        }
    }

    //--------------------守护线程----------------------------
   /* static ScheduledExecutorService scheduledExecutor = Executors
            .newSingleThreadScheduledExecutor(new ThreadFactory() {
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r);
                    t.setName("守护线程----xxxx----");
                    t.setDaemon(true);
                    return t;
                }
            });

    static public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
                                                            long delay, TimeUnit unit) {
        return scheduledExecutor.scheduleWithFixedDelay(command, initialDelay, delay, unit);
    }*/

    //------------------------------------------------

    /**
     * 延迟连接池, 创建一个定长线程池，支持定时及周期性任务执行。延迟执行示例代码如下：
     */

    public void test3() {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        //延迟一段时间就打印
        scheduledThreadPool.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("delay 3 seconds");
            }
        }, 1, 3, TimeUnit.SECONDS);

        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("delay 1 seconds, and excute every 3 seconds");
            }
        }, 1, 3, TimeUnit.SECONDS);


        // ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
        //每隔一段时间就打印...
     /*   scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                //throw new RuntimeException();
                System.out.println("================");
            }
        }, 1000, 5000, TimeUnit.MILLISECONDS);*/


    }


    //------------------------------------------------

    /**
     * 创建一个单线程化的线程池，它只会用唯一的工作线程来执行任务，保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下：
     */

    public void test4() {
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            singleThreadExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("打印单线程任务 :" + index);
                }
            });
        }


    }


    // 参考: https://blog.csdn.net/u011974987/article/details/51027795

}
